flowchart TD
%% ---------------------------------------------
%% Build & Image Pipeline
%% ---------------------------------------------
subgraph BuildPipeline["1. 📤 Push Phase"]
direction TB
Image["📦 Container Image"]
Registry["🌐 Container Registry ( Quay / Docker Hub)"]
Image -->|Pushed to| Registry
end
%% ---------------------------------------------
%% Deployment within Project / Namespace
%% ---------------------------------------------
subgraph Project["<span style='white-space:nowrap;'>2. 📁 OS: Project / K8s: Namespace</span>"]
direction TB
%% Image Reference Abstraction
IS["🏷️ OS: ImageStream & ImageStreamTag / K8s: Direct Image Reference / Container Tag"]
%% Workload Controllers
subgraph Workload["⚙️ Workload Controllers"]
direction TB
Deploy["📋 Deployment"]
RS["🔁 ReplicaSet"]
Deploy -->|Manages generation of| RS
end
%% Runtime Pods
subgraph Pods["▶️ Runtime Layer"]
direction LR
subgraph Pod1["🫛 Pod 1"]
direction TB
C1["🚀 Running Container"]
end
subgraph Pod2["🫛 Pod 2"]
direction TB
C2["🚀 Running Container"]
end
end
end
%% ---------------------------------------------
%% Cross-Stage Flow Connections
%% ---------------------------------------------
Registry -->|Tracks & imports metadata to| IS
IS -->|Injects image digest into| Deploy
RS -->|Spawns & maintains replicas| Pod1
RS -->|Spawns & maintains replicas| Pod2
%% ---------------------------------------------
%% Styling
%% ---------------------------------------------
classDef build fill:#f3f4f6,stroke:#4b5563,stroke-width:1px,color:#111827;
classDef project fill:#e0f2fe,stroke:#0369a1,stroke-width:2px,color:#082f49;
classDef workload fill:#ffffff,stroke:#0284c7,stroke-width:1px,color:#0f172a;
classDef pod fill:#f0fdf4,stroke:#16a34a,stroke-width:1px,color:#14532d;
class BuildPipeline,Code,BuildEngine,Image,Registry build;
class Project project;
class Workload,Deploy,RS,IS workload;
class Pods,Pod1,Pod2,C1,C2 pod;
OpenShift
Core concepts
Software
Containers & pods
For containers, images, registries see Docker cheatsheet.
- Pods
- Smallest deployable units in Kubernetes/OpenShift. Can contain multiple containers that share network namespace, storage, and lifecycle. Pods are ephemeral and should be managed through higher-level controllers.
- Pod lifecycle
- Managed through phases including Pending, Running, Succeeded, Failed, and Unknown. Pods have a restart policy; containers have individual health checks.
- Services
- Abstract way to expose applications running in pods. Types include ClusterIP, NodePort, LoadBalancer, and ExternalName. Support features like service mesh integration.
- Labels and annotations
- Key-value pairs for organizing and selecting Kubernetes resources. Annotations provide non-identifying metadata for automation and tooling.
Common commands:
| Description | Command |
|---|---|
| List pods in the current project | oc get pods |
| Show detailed pod info (events, probes, volumes) | oc describe pod <pod-name> |
| Follow pod logs | oc logs -f <pod-name> |
| Open an interactive shell in a pod | oc rsh <pod-name> |
| Execute a command in a running container | oc exec <pod-name> -- <command> |
| Forward a local port to a pod | oc port-forward <pod-name> <local-port>:<container-port> |
| Restart a pod (controller recreates it) | oc delete pod <pod-name> |
Projects & users
- Users
- Identity management integrated with enterprise systems (LDAP, OAuth, etc.). Supports Role-Based Access Control (RBAC) with custom roles and bindings.
- Kubernetes namespaces
- Virtual clusters within a physical cluster. Support resource quotas, network policies, and service isolation. Enable multi-tenancy and environment separation.
- Projects
- OpenShift’s extension of namespaces with additional security controls, routing, and monitoring features. Support for project templates and operator integration.
Common commands:
| Description | Command |
|---|---|
| Log in to a cluster | oc login <api-url> |
| Show the current user | oc whoami |
| Show the current project | oc project |
| List accessible projects | oc projects |
| Create and switch to a new project | oc new-project <name> |
| Switch to another project | oc project <name> |
| Show an overview of the current project | oc status |
| Grant a user a role in the current project | oc adm policy add-role-to-user <role> <user> |
| List your effective permissions | oc auth can-i --list |
Builds & Deployments
- Image streams
- OpenShift abstraction for managing container images. Support automatic updates, rollbacks, and deployment triggers. Enable image promotion across environments. The image stream contains Image stream tags, that reference the image digests (cryptographic reference of a container similar to git-sha).
- Jobs and CronJobs
- Manage pods that run to completion. Support for parallel processing, retry policies, and scheduled execution. Integration with cluster autoscaling.
- Operators
- Software extensions to Kubernetes that use custom resources to manage applications and their components. Automate operational tasks and complex deployments.
Common commands:
| Description | Command |
|---|---|
| Create an application from source code or an image | oc new-app <source-or-image> |
| List builds | oc get builds |
| Start a build manually | oc start-build <buildconfig-name> |
| Follow build logs | oc logs -f bc/<buildconfig-name> |
| List image streams | oc get imagestreams |
| Import an image into an image stream | oc import-image <imagestream-name> |
| Tag an image into an image stream | oc tag <source-image> <target>[:<tag>] |
| Watch a rollout’s progress | oc rollout status deploy/<name> |
| Roll back to the previous revision | oc rollout undo deploy/<name> |
| Scale a deployment | oc scale deploy/<name> --replicas=<n> |
Minimal Helm deployment
Helm packages Kubernetes resource templates into a chart and fills them with settings from values.yaml when installing or upgrading a release. This example runs one Shiny application pod through a Deployment, which recreates the pod if it is deleted; a separate bare Pod manifest is therefore unnecessary.
Assume a suitable Dockerfile already exists: the image must support OpenShift’s arbitrary non-root UID and the application must listen on 0.0.0.0:3838. The cluster must be able to pull the image; a private registry additionally requires image-pull credentials. No ImageStream is required when referencing an image directly.
File structure:
deploy/
├── project.yaml # Create separately before installing the chart
└── shiny/ # Helm chart
├── Chart.yaml # Chart metadata
├── values.yaml # Default settings
└── templates/
├── deployment.yaml # Pod template and replica management
├── pvc.yaml # Persistent application storage
└── service.yaml # Stable internal network endpoint
Project
deploy/project.yaml stays outside the chart so uninstalling the release does not delete the project:
apiVersion: project.openshift.io/v1
kind: Project
metadata:
name: shiny-demo- 1
-
Projectis the OpenShift equivalent of a Kubernetes namespace. It has to be created before the Helm release. - 2
-
nameidentifies the project and must match the namespace passed to Helm with--namespace.
Creating a Project typically requires administrator rights.
Chart metadata
deploy/shiny/Chart.yaml:
apiVersion: v2
name: shiny
version: 0.1.0- 1
-
apiVersion: v2uses the chart format supported by Helm 3 and later. - 2
-
versionis the chart’s package version. It is independent of the application’s image tag.
Values
deploy/shiny/values.yaml:
image:
repository: quay.io/MY_COMPANY/shiny
tag: "1.0.0"
replicaCount: 1
containerPort: 3838
service:
port: 3838
persistence:
size: 5Gi
mountPath: /data
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: "1"
memory: 1Gi- 1
-
imageidentifies the registry image to build and push before deployment. - 2
-
replicaCountsets the number of application pods maintained by the Deployment. - 3
-
containerPortmust match the actual listening port of the application and does not configure the application itself. - 4
-
service.portsets the port exposed by the internal Service. It can be different from the container port. - 5
-
persistencerequests 5 GiB of storage and mounts it at/data, where the application must explicitly write files that should survive pod replacement. - 6
-
requeststells the scheduler to account for 0.1 CPU and 256 MiB of memory per container when placing the pod. - 7
-
limitscaps CPU usage at one CPU through throttling and sets a 1 GiB memory limit, exceeding which can cause the container to be OOM-killed.
These resource sizes are examples and should be adjusted to measured application needs and project quotas.
Persistent storage
deploy/shiny/templates/pvc.yaml:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: "{{ .Release.Name }}-data"
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: "{{ .Values.persistence.size }}"- 1
-
A
PersistentVolumeClaim(PVC) requests persistent storage from the cluster rather than using the container’s ephemeral writable layer. - 2
- The release-specific name connects this claim to the Deployment’s volume reference.
- 3
-
ReadWriteOncepermits read-write mounting on one node at a time, not necessarily by only one pod. - 4
-
storagerequests the capacity configured invalues.yaml, using the cluster’s default StorageClass becausestorageClassNameis omitted.
This example assumes a default StorageClass with dynamic provisioning; otherwise, add spec.storageClassName for a suitable class or arrange a matching pre-provisioned volume with your administrator. Keep replicaCount: 1 for this single-writer example rather than scaling multiple pods against the same claim.
The mounted volume has its own permissions, replacing the image directory’s permissions; the storage driver and OpenShift’s allowed group settings must permit the assigned non-root user to write to it. Do not hard-code a UID or fsGroup outside the project’s allowed ranges.
Data survives pod replacement, but this chart manages the PVC, so helm uninstall also deletes the claim and may delete the underlying storage depending on its reclaim policy; arrange backups and a deliberate retention policy for important data.
Deployment and pods
deploy/shiny/templates/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: "{{ .Release.Name }}"
spec:
replicas: {{ .Values.replicaCount }}
strategy:
type: Recreate
selector:
matchLabels:
app: "{{ .Release.Name }}"
template:
metadata:
labels:
app: "{{ .Release.Name }}"
spec:
containers:
- name: shiny
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- name: http
containerPort: {{ .Values.containerPort }}
readinessProbe:
httpGet:
path: /
port: http
resources:
requests:
cpu: "{{ .Values.resources.requests.cpu }}"
memory: "{{ .Values.resources.requests.memory }}"
limits:
cpu: "{{ .Values.resources.limits.cpu }}"
memory: "{{ .Values.resources.limits.memory }}"
volumeMounts:
- name: data
mountPath: "{{ .Values.persistence.mountPath }}"
volumes:
- name: data
persistentVolumeClaim:
claimName: "{{ .Release.Name }}-data"- 1
-
.Release.Nameis supplied by Helm, so installing the release asshinynames the Deploymentshiny. - 2
-
.Valuesreads settings fromvalues.yaml, optionally overridden with Helm’s-for--setoptions. - 3
-
Recreatestops the old pod before creating its replacement during an update, avoiding overlapping writers and cross-node volume-attachment conflicts at the cost of downtime. - 4
-
selector.matchLabelsidentifies the Deployment’s pods and must match the labels undertemplate.metadata.labels. - 5
-
templatedefines the pods created by the Deployment, including their labels and container configuration. - 6
-
imagereferences the prebuilt registry image, whose default entrypoint and command start the application. - 7
-
The named
httpport documents the container’s listening port and lets the Service reference it by name. - 8
-
readinessProbechecks HTTP/and allows the pod to receive Service traffic only after the check succeeds. - 9
-
resourcesapplies the configured requests and limits to each application container, with explicit quotes keeping resource quantities as YAML strings. - 10
-
volumeMountsexposes the pod’sdatavolume at the configured path inside the container. - 11
-
volumesconnects the pod’sdatavolume to the PVC created by this release.
No fixed runAsUser is set, allowing OpenShift to assign a UID permitted by the project’s security policy.
Service
deploy/shiny/templates/service.yaml:
apiVersion: v1
kind: Service
metadata:
name: "{{ .Release.Name }}"
spec:
type: ClusterIP
selector:
app: "{{ .Release.Name }}"
ports:
- name: http
port: {{ .Values.service.port }}
targetPort: http- 1
- The Service uses the release name as its stable DNS name within the project.
- 2
-
ClusterIPexposes the application inside the cluster rather than publishing a port on your computer or an external hostname. - 3
-
selectorsends traffic to ready pods with the matchingapplabel. - 4
-
portis the Service’s listening port andtargetPortforwards traffic to the pod’s namedhttpport.
Deploying the chart
Run these steps from the directory containing deploy/ and your Dockerfile:
- Build and push the image: run
docker build -t quay.io/MY_COMPANY/shiny:1.0.0 .followed bydocker push quay.io/MY_COMPANY/shiny:1.0.0, using the same repository and tag as invalues.yaml. - Log in and provision the project: Have your admin login and run
oc apply -f deploy/project.yaml. - Check the chart locally: run
helm lint ./deploy/shinyandhelm template shiny ./deploy/shiny --namespace shiny-demoto inspect the generated manifests without deploying them. - Install or update: run
helm upgrade --install shiny ./deploy/shiny --namespace shiny-demo --wait --timeout 5m; Helm loads the chart’svalues.yamlautomatically and waits for the workload to become ready. - Inspect the workload and storage: run
oc get pods,services,pvc -n shiny-demoandoc logs -f deployment/shiny -n shiny-demo; if storage remainsPendingafter a pod is scheduled, inspectoc describe pvc shiny-data -n shiny-demofor provisioning or binding errors. - Test locally: run
oc port-forward service/shiny 3838:3838 -n shiny-demoand openhttp://localhost:3838while the command is running.
For a persistent external HTTP(S) endpoint, add an OpenShift Route pointing to this Service; port-forwarding is only a temporary local connection. If the application needs credentials, create a Kubernetes Secret in the same project outside the chart; keep actual secret values out of values.yaml and Git.
See the Helm chart documentation for chart structure and templating.
Infrastructure
- Nodes
- Physical or virtual machines running containerized workloads. Support various runtime classes and compute profiles. Can be managed through machine sets and autoscaling.
- Clusters
- Distributed systems for container orchestration. Support hybrid and multi-cloud deployments and advanced networking models.
- Service mesh
- Infrastructure layer for service-to-service communication. Provides traffic management, security, and observability features.
Common commands:
| Description | Command |
|---|---|
| List cluster nodes | oc get nodes |
| Show node resource usage | oc adm top nodes |
| List machine sets | oc get machinesets -n openshift-machine-api |
| Show installed cluster version and update channel | oc get clusterversion |
| List operators and their health | oc get clusteroperators |
More information: